//
//  RDDBModel.swift
//  test-ios
//
//  Created by wyz5204 on 2023/5/31.
//

import Foundation
import GRDB
import ReactiveSwift

class RDDBModel {
    
    private static var instance : RDDBModel?
    
    public static func shared() -> RDDBModel{
        if let shared = instance {
            return shared
        }
        let dbModel = RDDBModel()
        instance = dbModel ;
        return dbModel
    }
    
    public static func release(){
        instance = nil
    }
    
    
    // 数据库的初始化
    private var dbPool: DatabasePool
    private var crmId : String
    
    init() {
        do {
            let dbName = UserDefaults.standard.string(forKey: "crmId")
            guard let dbName = dbName else {
                throw EmptyError("crmId is nil")
            }
            self.crmId = dbName
            let dbPathUrl = try FileManager.default.url(for: .applicationSupportDirectory,
                                                        in: .userDomainMask,
                                                        appropriateFor: nil,
                                                        create:true).appendingPathComponent(dbName+".sqlite")
            // 获取到本地的路径 进行数据库的创建
            dbPool = try RDDatabase.recreate(dbPathUrl.path)
            // TODO 将来从这里将功能分出去
            try RDDatabase.migrateIfNeeded(dbPool)
            Logger.e("RDDBModel" , dbPool.path)
        }catch {
            fatalError("RDDBModel init is error \(error)")
        }
    }
    
    func getDBPath() -> String {
        return dbPool.path
    }
    
    func getCrmId() -> String{
        return crmId
    }
    
    // 保存组织列表
    func saveOrgs(_ orgs : [OrgBean]){
        print("saveOrgs" , dbPool.path)
        do {
            try dbPool.write({ database in
                // 插入前，进行组织清除
                let deleteCount = try? OrgBean.deleteAll(database)
                print("saveOrgs" , "delete = \(deleteCount)")
                // 进行插入数据
                orgs.forEach { org in
                    try? org.insert(database)
                }
            })
        }catch let error {
            print("saveOrgs " , error)
        }
    }
    
    func fetchOneOrg() -> OrgBean? {
        return try? dbPool.read({ database in
            return try? OrgBean.fetchOne(database)
        })
    }
    
    func fetchOrgs() -> [OrgBean]? {
        return try? dbPool.read({ db in
            return try? OrgBean.fetchAll(db)
        })
    }
    
    func findOrgById(_ orgId : Int) -> OrgBean? {
        return try? dbPool.read({ database in
            return try? OrgBean.filter(Column("id") == orgId).fetchOne(database)
        })
    }
    
    func getDefaultOrg() -> OrgBean? {
        var result : OrgBean?
        let orgId = getDefaultOrgId()
        defer {
            if(result == nil){
                clearUserDefaultsByName(RDDefaults.orgId)
            }else{
                if(result!.id != orgId){
                    setDefaultOrgId(result!.id)
                }
            }
        }
        if(orgId <= 0){
            result = fetchOneOrg()
        }else{
            result = findOrgById(orgId)
        }
        return result
    }
    
    func getDefaultOrgId() -> Int {
        return UserDefaults.standard.integer(forKey: RDDefaults.orgId)
    }
    
    func setDefaultOrgId(_ orgId : Int) {
        UserDefaults.standard.set(orgId, forKey: RDDefaults.orgId)
    }
    
    func clearUserDefaultsByName(_ name : String){
        UserDefaults.standard.removeObject(forKey: name)
    }
    
    ///------------------------ SessionDAO ------------------------
    func getSessionList() -> [ChatSession]? {
        return try? dbPool.read({ db in
            return try? ChatSession.order(ChatSession.updateTime.desc).fetchAll(db)
        })
    }
    
    func saveSession(_ sessions : [ChatSession]){
        try? dbPool.write({ db in
            sessions.forEach { session in
                if(session._id < 0){
                    try? session.insert(db)
                }else{
                    try? session.update(db)
                }
            }
        })
    }
    
    
    func saveSingleSession(_ session : ChatSession){
        try? dbPool.write({ db in
            Logger.e(0)
            let value = try? ChatSession.filter(Column("id") == session.id).fetchOne(db)
            if(value != nil){
                let newValue = session
                try newValue.updateChanges(db, from: value!)
                Logger.e(1 )
            }else{
                try session.insert(db)
                Logger.e(2 )
            }
        })
    }
}
